package com.timothy.android;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;

import com.timothy.android.util.ActivityStackControlUtil;
import com.timothy.android.util.SysUtil;
import com.timothy.service.CommunicationService;
import com.timothy.service.MessageSenderUtil;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import android.content.SharedPreferences; 
import android.content.pm.ActivityInfo;


public class LoginActivity extends Activity {
	/** Called when the activity is first created. */
	private static final String LOG_TAG = "LoginActivity";
	
	private TextView loginTitle = null;
	
	private TextView demoVoteHintTV = null;
	private TextView timeTV = null;
	
	private EditText hostAddr = null;
	private EditText hostPort = null;
	
	private Button livingVoteBtn = null;
	private Button demoVoteBtn = null;
	
	SharedPreferences sharedPreferences;
	
	private ProgressDialog progressDialog = null;
	private MyTask myTask = null;
	private final static Integer WAITING_TIME = 10000;
	
    //receive quit command
    @Override
    protected void onStart() {
    	Log.i(LOG_TAG, "onStart()...");
    	int flag = getIntent().getIntExtra("flag", 0);
    	Log.i(LOG_TAG, "flag="+flag);
    	if(flag == SysUtil.EXIT_APPLICATION){
    		finish();
    	}
    	super.onResume();
    }
    
    //when activity is single case,when restart activity, system will no call methods like oncreate->onstart
    @Override
    protected void onNewIntent(Intent intent) {
    	Log.i(LOG_TAG, "onNewIntent()...");
    	int flag = getIntent().getIntExtra("flag", 0);
    	Log.i(LOG_TAG, "flag="+flag);
    	if(flag == SysUtil.EXIT_APPLICATION){
    		finish();
    	}
    	super.onNewIntent(intent);
    }
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Log.i(LOG_TAG, "onCreate()...");
		
		this.requestWindowFeature(Window.FEATURE_NO_TITLE);
		
		ActivityStackControlUtil.add(this);//add to activity stack to manage
		setContentView(R.layout.login);
		
		//set orientation to portrait
		this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
		//keep screen no locked
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
		
		loginTitle = (TextView) this.findViewById(R.id.loginTitle);
		loginTitle.setText("Login");
		
		hostAddr = (EditText) this.findViewById(R.id.hostAddr);
		hostPort = (EditText) this.findViewById(R.id.hostPort);
		
		//get information from history, if exist, set history information to components
	    sharedPreferences = this.getSharedPreferences("powersmart",MODE_PRIVATE); 
		String preHostAddr = sharedPreferences.getString("pcip", null);  
		int preHostPort = sharedPreferences.getInt("pcport", 0);
		Log.i(LOG_TAG, "load history from sharedPreferences:host="+preHostAddr);
		Log.i(LOG_TAG, "load history from sharedPreferences:port="+preHostPort);
		if(preHostAddr!=null) hostAddr.setText(preHostAddr);
		if(preHostPort!=0) hostPort.setText(String.valueOf(preHostPort));
		
		//click button [Living Vote], enter living vote
		livingVoteBtn = (Button) this.findViewById(R.id.livingVoteBtn);
		livingVoteBtn.setOnClickListener(new Button.OnClickListener() {
			public void onClick(View v) {
//				isLivingVote = true;
				MessageSenderUtil.MODE = 1;
				livingVoteBtn.setEnabled(false);
				demoVoteBtn.setEnabled(false);
				connectServer();
			}			
		});
		
		//click button [Demo Vote], enter demo vote
		demoVoteBtn = (Button) this.findViewById(R.id.demoVoteBtn);
		demoVoteBtn.setOnClickListener(new Button.OnClickListener() {
			public void onClick(View v) {
				MessageSenderUtil.MODE = 2;
				livingVoteBtn.setEnabled(false);
				demoVoteBtn.setEnabled(false);
				connectServer();
			}			
		});
		
		demoVoteHintTV = (TextView) this.findViewById(R.id.demoVoteHintTV);
		demoVoteHintTV.setText(R.string.msg_tv_hint);
		
		timeTV = (TextView) this.findViewById(R.id.timeTV);
		timeTV.setText(R.string.msg_tv_version);
		
		Log.i(LOG_TAG, "--------------onCreate() end--------------");
	}
	
	public void connectServer(){
		MessageSenderUtil.PC_IP =  hostAddr.getText().toString();
		MessageSenderUtil.PC_PORT = Integer.valueOf( hostPort.getText().toString() );
		
		//get wifi service 
//        WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
        //check wifi is enabled 
//        if (!wifiManager.isWifiEnabled()) { 
//        	ShowDialog("Wifi In Your mobile is not available!");
//        	//wifiManager.setWifiEnabled(true);  
//        	return;
//        } 
        
        //test wifi network
//        MessageSenderUtil.PHONE_IP = getWifiIP();
//        MessageSenderUtil.PHONE_IP = getMobileIp();

		if (getWifiIP() != null && getWifiIP().trim().length() > 0 && !getWifiIP().trim().equals("0.0.0.0")) {
			MessageSenderUtil.PHONE_IP = getWifiIP();
		} else if (getMobileIp() != null && getMobileIp().trim().length() > 0 && !getMobileIp().trim().equals("0.0.0.0")) {
			MessageSenderUtil.PHONE_IP = getMobileIp();
		} else {
			ShowDialog("Your mobile is not in a available NetWork!");
		}
		
    	myTask = new MyTask();
    	myTask.execute("");
        
/*        if ( MessageSenderUtil.PHONE_IP==null || MessageSenderUtil.PHONE_IP.equals("") || MessageSenderUtil.PHONE_IP.equals("0.0.0.0")) { 
        	ShowDialog("Your mobile is not in a available NetWork!");
        	return;
        }else if(pingIP(MessageSenderUtil.PC_IP)){
        	ShowDialog("Server is not available");
        }else{
        	//connect server by communication service
        	myTask = new MyTask();
        	myTask.execute("");
        }*/
	}
	
    @Override
    protected void onResume() {
    	super.onStart();
    	Log.i(LOG_TAG, "onResume()...");
    }
	
	protected void processMessage(int what, String content) {
		Log.i(LOG_TAG,"processMessage()...");
		Log.i(LOG_TAG,"what="+what+" content=" + content);
		if( CommunicationService.MSG_BASE_STATION == what ) {//For living vote mode
			myTask.cancel(true);
			livingVoteBtn.setEnabled(true);
			demoVoteBtn.setEnabled(true);
			
			Intent intent = new Intent();
			intent.putExtra("baseStationStr", content);//save baseStationStr
			intent.putExtra("hostIp", hostAddr.getText().toString());//save hostIp
			intent.putExtra("hostPort", Integer.valueOf( hostPort.getText().toString()));//save hostPort
			intent.setClass( getBaseContext(), SessionsLiveVote.class);
			finish();
			startActivity(intent);
			return;
		}
		
//		if (CommunicationService.MSG_BASE_STATION == what ) {//fake test code//For demo vote mode
		if (CommunicationService.MSG_DEMO_GET_SESSIONS == what ) {
			myTask.cancel(true);
			//go to home page
			Intent intent = new Intent();
			intent.putExtra("demoSessionStr", content);//save baseStationStr
//			intent.putExtra("demoSessionStr", "<Content><Session Name=\"a\"/><Session Name=\"b\"/></Content>");//save baseStationStr
			intent.setClass(this.getBaseContext(), SessionsDemoVote.class);
			finish();//finish current activity
			startActivity(intent);
		} 
	}
	
	/*public boolean pingIP(String ipAddress) {
		Log.i(LOG_TAG, "Ping Poller Starts...");
		// String ipAddress = "localhost";
		boolean pingResult = true;
		try {
			InetAddress inet = InetAddress.getByName(ipAddress);
			System.out.println("Sending Ping Request to " + ipAddress);
			Log.i(LOG_TAG, "IP:"+ipAddress);
			boolean status = inet.isReachable(5000); // Timeout = 5000 milli
			if (status) {
				Log.i(LOG_TAG, "Status : Host is reachable");
			} else {
				Log.i(LOG_TAG, "Status : Host is not reachable");
				pingResult = false;
			}
		} catch (UnknownHostException e) {
			System.err.println("Host does not exists");
			Log.i(LOG_TAG, "Host does not exists");
			pingResult = false;
		} catch (IOException e) {
			System.err.println("Error in reaching the Host");
			Log.i(LOG_TAG, "Error in reaching the Host");
			pingResult = false;
		}
		return pingResult;
	}*/
	
	//get ip base WIFI network
	private String getWifiIP() {
		// get wifi service
		WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
		// is wifi enabled
/*		if (!wifiManager.isWifiEnabled()) {
			wifiManager.setWifiEnabled(true);
		}*/
		WifiInfo wifiInfo = wifiManager.getConnectionInfo();
		int ipAddress = wifiInfo.getIpAddress();
		String ip = (ipAddress& 0xFF) + "." + ((ipAddress >> 8) & 0xFF) + "." + ((ipAddress >> 16) & 0xFF)+ "." + (ipAddress >> 24 & 0xFF);
		return ip;
	}
	
	//get ip base GPRS network
	public String getMobileIp() {
		try {
			for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
				NetworkInterface intf = en.nextElement();
				for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
					InetAddress inetAddress = enumIpAddr.nextElement();
					if (!inetAddress.isLoopbackAddress()) {
						return inetAddress.getHostAddress().toString();
					}
				}
			}
		} catch (SocketException ex) {
		}
		return null;
	}
	
	//===========================eneter connect start================================
	
    void doBindService() {
        Log.i(LOG_TAG,"doBindService()...");
        bindService(new Intent(LoginActivity.this, CommunicationService.class), commConnection, Context.BIND_AUTO_CREATE);
    }

    void doUnbindService() {
    	Log.i(LOG_TAG,"doUnbindService()...");
        if (eneterIsBound) {
        	unbindService(commConnection);
        	eneterIsBound = false;
        } 
    }
    
    //message receive 
    private Messenger eneterRMessenger = new Messenger( new EneterIncomingHandler() );
    private Messenger eneterSMessenger = null;
    private boolean eneterIsBound;
    
	private ServiceConnection commConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
        	Log.i(LOG_TAG,"commConnection.onServiceConnected()...");
        	eneterSMessenger = new Messenger( service );
            try {
                Message msg = Message.obtain(null, CommunicationService.MSG_REGISTER_CLIENT);
                msg.replyTo = eneterRMessenger;
                eneterSMessenger.send(msg);
            } catch (RemoteException e) {
            }
            eneterIsBound = true;
	        String message = null;
	        
	        if(MessageSenderUtil.MODE == 1){
	        	message = MessageSenderUtil.addHeader(MessageSenderUtil.Get_Base_Stations);
	        	Log.i(LOG_TAG,"Living vote message:"+message);
	        }else{
	        	message = MessageSenderUtil.addHeader(MessageSenderUtil.Get_Demo_Sessions);
	        	Log.i(LOG_TAG,"Demo vote message:"+message);
	        }
	        
	        if(!sendMessage(message) ) {
	        	ShowDialog("Can not login Server!");
	        	doUnbindService();
	        }else{
				//save information to local
				SharedPreferences.Editor editor = sharedPreferences.edit();
				editor.putString("pcip", hostAddr.getText().toString());  
				editor.putInt("pcport", Integer.valueOf(hostPort.getText().toString())); 
				editor.commit();
			}
	        
	        Log.i(LOG_TAG,"eneterIsBound:"+eneterIsBound);
       }
       
       public void onServiceDisconnected(ComponentName className) {
    	   Log.i(LOG_TAG,"commConnection.onServiceDisconnected()...");
       	 	Message msg = Message.obtain(null, CommunicationService.MSG_UNREGISTER_CLIENT);
            msg.replyTo = eneterRMessenger;
            try {
            	eneterSMessenger.send(msg);
            } catch (RemoteException e) {
            }
            eneterIsBound = false;
            
            Log.i(LOG_TAG,"eneterIsBound:"+eneterIsBound);
       }
    };
    
   //message send 
    public boolean sendMessage(String command){
    	Log.i(LOG_TAG, "sendMessage()...");
    	Log.i(LOG_TAG, "send mesage:\n"+command);
    	Log.i(LOG_TAG, "to:"+MessageSenderUtil.PC_IP);
    	Message msg = Message.obtain(null,CommunicationService.MSG_SEND_SERVER,command);
        try {
        	eneterSMessenger.send(msg);
			Log.i(LOG_TAG, "CommunicationService.MSG_SEND_SERVERE=" + CommunicationService.MSG_SEND_SERVER);
		} catch (RemoteException e) {
			Log.i(LOG_TAG, "RemoteException:"+e.getMessage());
		}
		Log.i(LOG_TAG, "--------------sendMessage() end.--------------");
    	return true;
    }
    
    class EneterIncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
        	Log.i(LOG_TAG,"Receive message from " + MessageSenderUtil.PC_IP);
        	Log.i(LOG_TAG,"Message Type: " + msg.what);
        	Log.i(LOG_TAG,"Message Content: " + (String)msg.obj);
        	
        	processMessage( msg.what, (String)msg.obj );
        	
        	Log.i(LOG_TAG,"--------------EneterIncomingHandler.handleMessage() End--------------");
        }
    }
    //===========================eneter connect end================================
	
	//===========================quit set start================================
	private long exitTime = 0;
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
			if(progressDialog!=null){
				progressDialog.dismiss();
			}
			if ((System.currentTimeMillis() - exitTime) > 2000) {
				Toast.makeText(getApplicationContext(), "Click again to quit!",Toast.LENGTH_SHORT).show();
				exitTime = System.currentTimeMillis();
			} else {
				finish();
				ActivityStackControlUtil.finishProgram();
				System.exit(0);
				
				Intent mIntent = new Intent();
				mIntent.setClass(getBaseContext(), LoginActivity.class);
				mIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
				mIntent.putExtra("flag", 0x0001);
				startActivity(mIntent);
			}
			return true;
		}
		return super.onKeyDown(keyCode, event);
	}
	//===========================quit set end================================
	
	//===========================waiting window start================================
	private class MyTask extends AsyncTask<String, Integer, String> {
    	@Override
    	protected void onPreExecute() {
    		Log.i(LOG_TAG, "onPreExecute() called");
    		progressDialog = ProgressDialog.show(LoginActivity.this, "Loading...", "Please wait...", true, false); 
    	}
		@Override
		protected String doInBackground(String... params) {
			Log.i(LOG_TAG, "doInBackground(Params... params) called");
			try {
				doBindService();
				Thread.sleep(WAITING_TIME);  
				return new String("");
				
			} catch (Exception e) {
				Log.e(LOG_TAG, e.getMessage());
			}
			return null;
		}
		@Override
    	protected void onProgressUpdate(Integer... progresses) {
			Log.i(LOG_TAG, "onProgressUpdate(Progress... progresses) called");
    	}
		@Override
		protected void onPostExecute(String result) {
			Log.i(LOG_TAG, "onPostExecute(Result result) called");
			if(progressDialog.isShowing()){
				progressDialog.dismiss();
			}
			doUnbindService();
			livingVoteBtn.setEnabled(true);
			demoVoteBtn.setEnabled(true);
			
			Toast.makeText(getBaseContext(), "Time out, please try again!", Toast.LENGTH_LONG).show();
		}
		@Override
		protected void onCancelled() {
			Log.i(LOG_TAG, "onCancelled() called");
			if(progressDialog.isShowing()){
				progressDialog.dismiss();
			}
		}
    }
	
	//===========================waiting window end================================
	
	//Show Dialog
	public void ShowDialog(String msg) {
		new AlertDialog.Builder(this).setTitle("Note").setMessage(msg)
				.setPositiveButton("OK", new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
					}
				}).show();
	}
}
